import axios from "axios";
import {
  HttpCache,
  HttpPending,
  addReqCancel,
  checkReqAuth,
  httpRetry,
  refreshTokenAndRetry
} from "./helper";
import { showLoading, hideLoading } from "@/hooks/useLoading";
import $i18n from "@/plugins/i18n";

const instance = axios.create({
  baseURL: VITE_ENV.VITE_API_BASE_URL,
  responseType: "json",
  timeout: VITE_ENV.VITE_HTTP_TIMEOUT,
  withCredentials: false,
  headers: {
    "Content-Type": "application/json;charset=UTF-8"
  },
  transformResponse: data => {
    return JSON.parse(data);
    // const obj=JSON.parse(data,(k,v) =>{
    //   if(Number.isInteger(v)&&!Number.isSafeInteger(v)){
    //     return BigInt(`${v}`)
    //   }
    //   return v
    // })
    // return obj
  }
});
const IS_MOCK = VITE_ENV.VITE_MOCK_API;
const HTTP_RETRY = VITE_ENV.VITE_HTTP_RETRY;
const httpPending = new HttpPending();
const httpCache = new HttpCache();
const succCode = [200, 0, 1000];
instance.interceptors.request.use(
  function (config) {
    if (IS_MOCK) {
      delete config.data;
      delete config.params;
    }
    if (config.loading) {
      showLoading();
    }
    addReqCancel(config);
    checkReqAuth(config);
    httpCache.checkCache(config);
    httpPending.addPending(config);
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  function (response) {
    const codes = response.config.succCode ?? succCode;
    if (response.config.loading) {
      hideLoading();
    }
    httpPending.removePending(response.config);
    httpCache.addCache(response);
    if (codes.includes(response.data.code)) {
      return Promise.resolve(response.data);
    } else {
      const msg = response.data.message || response.data.msg;
      const errMsg = $i18n.global.t(`${response.data.code}`);
      return Promise.reject(msg);
    }
  },
  async function (error) {
    if (error.config?.loading || error.message._config?.loading) {
      hideLoading();
    }
    httpPending.removePending(error.config);
    if (axios.isCancel(error) && error.message) {
      const msgData: any = error.message;
      console.warn("Cancel Request!", msgData);
      httpPending.removePending(msgData._config);
      if (msgData._cache && msgData.data) {
        return Promise.resolve(msgData.data);
      }
      return Promise.reject(error);
    } else {
      if (error.config?._skip || error.message._config?._skip) {
        return Promise.reject(error);
      }
      if ([401, 403].includes(error.response.status)) {
        const res = await refreshTokenAndRetry(error.config);
        return Promise.resolve(res);
      }
      if (HTTP_RETRY) {
        const res = await httpRetry(error.config);
        return Promise.resolve(res);
      }
    }
    return Promise.reject(error);
  }
);

export default instance;

export { httpPending, httpCache };
